#pragma once

#include <iostream>
#include <cstring>
#include <sys/epoll.h>
#include <unistd.h>

#include "log.hpp"

namespace Epoll
{
    const static int defaultepfd = -1;
    const static int size = 128;

    class Epoller
    {
        int _epfd;

    public:
        Epoller() : _epfd(defaultepfd)
        {
        }

        ~Epoller()
        {
            if (_epfd >= 0)
            {
                close(_epfd);
            }
            lg.LogMessage(Info, "epoll close success\n");
        }

        void DelEvent(int sockfd)
        {
            int n = ::epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr);
            if (n < 0)
            {
                lg.LogMessage(Error,"epoll_ctr del error,%s : %d\n", strerror(errno),errno);
            }
        }

        void AddEvent(int sockfd, uint32_t events)
        {
            struct epoll_event ev;
            ev.events = events;
            ev.data.fd = sockfd; // 给用户的,不是给内核的

            int n = ::epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &ev);
            // 向 epfd 模型对 sockfd 注册事件

            if (n < 0)
            {
                lg.LogMessage(Error, "epoll_ctl add error");
            }
        }

        void InitEoller()
        {
            _epfd = ::epoll_create(size); // 创建大小为 size 的模型
            if (defaultepfd == _epfd)
            {
                lg.LogMessage(Fatal, "epoll_create error, %s:%d\n", strerror(errno), errno);
                exit(4);
            }
        }

        int Wait(struct epoll_event *revs, int maxevents, int timeout)
        {
            int n = ::epoll_wait(_epfd, revs, maxevents, timeout);
            return n;
        }
    };
}